package com.imooc.controller;

import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.databind.ser.std.StdKeySerializers.Default;
import com.imooc.domain.MiaoshaOrder;
import com.imooc.domain.MiaoshaUser;
import com.imooc.rabbitmq.MiaoshaMessage;
import com.imooc.rabbitmq.MqSender;
import com.imooc.redis.AccessKey;
import com.imooc.redis.GoodsKey;
import com.imooc.redis.MiaoshaKey;
import com.imooc.redis.RedisService;
import com.imooc.result.CodeMsg;
import com.imooc.result.Result;
import com.imooc.service.GoodsService;
import com.imooc.service.MiaoshaService;
import com.imooc.service.MiaoshaUserService;
import com.imooc.service.OrderService;
import com.imooc.utils.MD5Util;
import com.imooc.vo.GoodsVo;

@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean{
	
	@Autowired
	MiaoshaUserService userService;
	
	@Autowired
	GoodsService goodsService;
	
	@Autowired
	RedisService redisService;
	
	@Autowired
	OrderService orderService;
	
	@Autowired
	MiaoshaService miaoshaService;
	
	@Autowired
	MqSender mqSender;
	
	
	private Map<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();
	
	
	/**
	 * 系统初始化时 加载库存（回调）
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		List<GoodsVo> goodsList = goodsService.listGoodsVo();
		if(goodsList == null){
			return;
		}
		for(GoodsVo goods : goodsList){
			 // 从db查询库存放入redis
			redisService.set(GoodsKey.GET_GOODS_STOCK, ""+goods.getId(), goods.getGoodsStock());
			localOverMap.put(goods.getId(), false); // 内存标记 - 秒杀是否结束（该商品是否秒杀完了）
		}
	}
	
	
//	@RequestMapping("/do_miaosha")
//	public String list(Model model, MiaoshaUser user, 
//			@RequestParam("goodsId") long goodsId){
//		model.addAttribute("user", user);
//		if(user == null)return "login";
//		
//		// 判断库存
//		GoodsVo goods = goodsService.getGoodsByGoodsId(goodsId);
//		Integer stock = goods.getStockCount();
//		if(stock <= 0){
//			model.addAttribute("errorMsg", CodeMsg.MIAOSHA_OVER.getMsg());
//			return "miaosha_fail";
//		}
//		// 判断是否已经秒杀到了
//		MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdAndGoodsId(user.getId(), goodsId);
//		if(order != null){
//			model.addAttribute("errorMsg", CodeMsg.REPEAT_MIAOSHA.getMsg());
//			return "miaosha_fail";
//		}
//		// 减库存，下订单，秒杀订单
//		OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
//		model.addAttribute("orderInfo", orderInfo);
//		model.addAttribute("goods", goods);
//		return "order_detail";
//		 
//	}
	
	 
	
	@RequestMapping(value="/{path}/do_miaosha",method=RequestMethod.POST)
	@ResponseBody
	public Result list(Model model, MiaoshaUser user, 
			@RequestParam("goodsId") long goodsId,
			@RequestParam("path") String path){
		model.addAttribute("user", user);
		if(user == null)return Result.error(CodeMsg.SESSION_ERROR);
		
		// 验证path
		boolean check = miaoshaService.checkPath(user, goodsId, path);
		if(!check){
			return Result.error(CodeMsg.REQUEST_ILLEGAL);
		}
		
		// 使用内存标记减少对redis的访问
		boolean over = localOverMap.get(goodsId);
		if(over){
			return Result.error(CodeMsg.MIAOSHA_OVER);
		}
		
		// 接口秒杀优化start - 预减库存
		long stock = redisService.decr(GoodsKey.GET_GOODS_STOCK, ""+goodsId);
		 if(stock < 0){
			 localOverMap.put(goodsId, true);
			 return Result.error(CodeMsg.MIAOSHA_OVER); // 秒杀失败
		 }
		 // 判断是否已经秒杀到了
		 MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdAndGoodsId(user.getId(), goodsId);
		 if(order != null){
			 return Result.error(CodeMsg.REPEAT_MIAOSHA); // 不能重复秒杀
		 }
		 // 入队（mq）
		 MiaoshaMessage message = new MiaoshaMessage(); 
		 message.setUser(user);
		 message.setGoodsId(goodsId);
		 
		 mqSender.sendMiaoshaMessage(message);
		 return Result.success(0); // 排队中...
	}

	
	/**
	 * 轮询（是否秒杀成功）
	 *
	 * 成功 ： 订单id
	 * 库存不足 ： -1
	 * 排队中 ：0 (还未出队)
	 */
	@RequestMapping(value="/result", method=RequestMethod.GET)
	@ResponseBody
	public Result<Long> miaoshaResult(Model model, MiaoshaUser user, @RequestParam("goodsId") long goodsId){
		model.addAttribute("user", user);
		if(user == null){
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
		return Result.success(result);
	}
	
	
	/**
	 * 获取秒杀加密路径
	 * @param model
	 * @param user
	 * @param goodsId
	 * @param verifyCode
	 * @return
	 */
	@RequestMapping(value="/path", method=RequestMethod.GET)
	@ResponseBody
	public Result<String> getMaioshaPath(HttpServletRequest request, MiaoshaUser user,
			@RequestParam("goodsId") long goodsId,
			@RequestParam(value="verifyCode", defaultValue="0") int verifyCode){
		if(user == null)return Result.error(CodeMsg.SESSION_ERROR);
		
		//防止刷限流
		//查询访问次数
		String uri = request.getRequestURI();
		String key = uri + "_" + user.getId();
		Integer count = redisService.get(AccessKey.ACCESS_LIMIT_READ, key, Integer.class);
		if(count == null){
			redisService.set(AccessKey.ACCESS_LIMIT_READ, key, 1);
		}else if(count < 5){
			// +1
			redisService.incr(AccessKey.ACCESS_LIMIT_READ, key);
		}else{
			return Result.error(CodeMsg.ACCESS_LIMIT);
		}
		
		
		// 验证码校验
		boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
		if(!check){
			return Result.error(CodeMsg.VERIFYCODE_ERROR);
		}
		
		String path = miaoshaService.createMiaoshaPath(user, goodsId);
		
		return Result.success(path);
	}
	
	/**
	 * 验证码
	 * @return
	 */
	@RequestMapping(value="/verifyCode", method=RequestMethod.GET)
	@ResponseBody
	public Result<Long> verifyCode(HttpServletResponse response, Model model, MiaoshaUser user, @RequestParam("goodsId") long goodsId){
		model.addAttribute("user", user);
		if(user == null){
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		try{
			BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
			OutputStream out = response.getOutputStream();
			ImageIO.write(image, "JPEG", out);
			out.flush();
			out.close();
			return null;
		}catch(Exception e){
			e.printStackTrace();
			return Result.error(CodeMsg.MIAOSHA_FAIL);
		}
	}
	
	
	
	
	
	
	

}
